package com.iyao_app.preview;

import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;

/**
 * 作者 :  胡家兵
 * 时间 :  2017/11/27.
 */

public class ScaleDragDetector implements ScaleGestureDetector.OnScaleGestureListener {
    private static final int INVALID_POINTER_ID = -1;
    private final float mTouchSlop;
    private final float mMinimumVelocity;
    private final ScaleGestureDetector mScaleDetector;
    private final OnScaleDragGestureListener mScaleDragGestureListener;
    private VelocityTracker mVelocityTracker;
    private boolean mIsDragging;
    float mLastTouchX;
    float mLastTouchY;
    private int mActivePointerId = -1;
    private int mActivePointerIndex = 0;

    public ScaleDragDetector(Context context, OnScaleDragGestureListener scaleDragGestureListener) {
        this.mScaleDetector = new ScaleGestureDetector(context, this);
        this.mScaleDragGestureListener = scaleDragGestureListener;
        ViewConfiguration configuration = ViewConfiguration.get(context);
        this.mMinimumVelocity = (float)configuration.getScaledMinimumFlingVelocity();
        this.mTouchSlop = (float)configuration.getScaledTouchSlop();
    }

    public boolean onScale(ScaleGestureDetector detector) {
        float scaleFactor = detector.getScaleFactor();
        if(!Float.isNaN(scaleFactor) && !Float.isInfinite(scaleFactor)) {
            this.mScaleDragGestureListener.onScale(scaleFactor, detector.getFocusX(), detector.getFocusY());
            return true;
        } else {
            return false;
        }
    }

    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }

    public void onScaleEnd(ScaleGestureDetector detector) {
        this.mScaleDragGestureListener.onScaleEnd();
    }

    public boolean isScaling() {
        return this.mScaleDetector.isInProgress();
    }

    public boolean isDragging() {
        return this.mIsDragging;
    }

    private float getActiveX(MotionEvent ev) {
        try {
            return MotionEventCompat.getX(ev, this.mActivePointerIndex);
        } catch (Exception var3) {
            return ev.getX();
        }
    }

    private float getActiveY(MotionEvent ev) {
        try {
            return MotionEventCompat.getY(ev, this.mActivePointerIndex);
        } catch (Exception var3) {
            return ev.getY();
        }
    }

    public boolean onTouchEvent(MotionEvent ev) {
        this.mScaleDetector.onTouchEvent(ev);
        int action = MotionEventCompat.getActionMasked(ev);
        this.onTouchActivePointer(action, ev);
        this.onTouchDragEvent(action, ev);
        return true;
    }

    private void onTouchActivePointer(int action, MotionEvent ev) {
        switch(action) {
            case 0:
                this.mActivePointerId = ev.getPointerId(0);
                break;
            case 1:
            case 3:
                this.mActivePointerId = -1;
            case 2:
            case 4:
            case 5:
            default:
                break;
            case 6:
                int pointerIndex = MotionEventCompat.getActionIndex(ev);
                int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
                if(pointerId == this.mActivePointerId) {
                    int newPointerIndex = pointerIndex == 0?1:0;
                    this.mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
                    this.mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);
                    this.mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);
                }
        }

        this.mActivePointerIndex = MotionEventCompat.findPointerIndex(ev, this.mActivePointerId != -1?this.mActivePointerId:0);
    }

    private void onTouchDragEvent(int action, MotionEvent ev) {
        float x;
        float y;
        switch(action) {
            case 0:
                this.mVelocityTracker = VelocityTracker.obtain();
                if(null != this.mVelocityTracker) {
                    this.mVelocityTracker.addMovement(ev);
                }

                this.mLastTouchX = this.getActiveX(ev);
                this.mLastTouchY = this.getActiveY(ev);
                this.mIsDragging = false;
                break;
            case 1:
                if(this.mIsDragging && null != this.mVelocityTracker) {
                    this.mLastTouchX = this.getActiveX(ev);
                    this.mLastTouchY = this.getActiveY(ev);
                    this.mVelocityTracker.addMovement(ev);
                    this.mVelocityTracker.computeCurrentVelocity(1000);
                    x = this.mVelocityTracker.getXVelocity();
                    y = this.mVelocityTracker.getYVelocity();
                    if(Math.max(Math.abs(x), Math.abs(y)) >= this.mMinimumVelocity) {
                        this.mScaleDragGestureListener.onFling(this.mLastTouchX, this.mLastTouchY, -x, -y);
                    }
                }

                if(null != this.mVelocityTracker) {
                    this.mVelocityTracker.recycle();
                    this.mVelocityTracker = null;
                }
                break;
            case 2:
                x = this.getActiveX(ev);
                y = this.getActiveY(ev);
                float dx = x - this.mLastTouchX;
                float dy = y - this.mLastTouchY;
                if(!this.mIsDragging) {
                    this.mIsDragging = Math.sqrt((double)(dx * dx + dy * dy)) >= (double)this.mTouchSlop;
                }

                if(this.mIsDragging) {
                    this.mScaleDragGestureListener.onDrag(dx, dy);
                    this.mLastTouchX = x;
                    this.mLastTouchY = y;
                    if(null != this.mVelocityTracker) {
                        this.mVelocityTracker.addMovement(ev);
                    }
                }
                break;
            case 3:
                if(null != this.mVelocityTracker) {
                    this.mVelocityTracker.recycle();
                    this.mVelocityTracker = null;
                }
        }

    }
}
